/*
 * Network.java
 *
 * Created on January 27, 2007, 11:10 PM
 *
 * @author Greg Robinson
 */

package neural;

public class Network {
    
    private Layer[] net;
    public char default_activation = Layer.H_TANGENT;
    
    /**
     * Creates a new instance of Network with the number of neurons
     * in each layer specified in elements of numNeurons, full synapse,
     * and random weights.
     */
    public Network(int[] numNeurons, int numInputs, char activation) {
        if (activation == -1) activation = this.default_activation;
        int i;
        this.net[0] = new Layer(numNeurons[0], numInputs, activation);
        for (i = 1; i < numNeurons.length; i++){
            net[i] = new Layer(numNeurons[i], numNeurons[i-1], Layer.H_TANGENT);
        }
    }
    
    /**
     * Creates a new instance of Network with the number of neurons in each
     * layer specified in elements of numNeurons, random weights, and
     * connections specified in connections.
     */
    public Network(
            int[] numNeurons,
            int numInputs,
            int[][][] connections,
            char activation) {
        if (activation == -1) activation = this.default_activation;
        int i;
        this.net[0] = new Layer(
                numNeurons[0],
                numInputs,
                connections[0],
                Layer.H_TANGENT);
        for (i = 1; i < numNeurons.length; i++){
            net[i] = new Layer(numNeurons[i], numNeurons[i-1], activation);
        }
    }
    
    /**
     * Creates a new instance of Network with the number of neurons in each
     * layer specified in elements of numNeurons, a full synapse, and
     * random weights.
     */
    public Network(
            int[] numNeurons,
            int numInputs,
            double[][][] weights,
            char activation) {
        if (activation == -1) activation = this.default_activation;
        int i;
        this.net[0] = new Layer(
                numNeurons[0],
                numInputs,
                weights[0],
                activation);
        for (i = 1; i < numNeurons.length; i++){
            net[i] = new Layer(numNeurons[i], numNeurons[i-1], activation);
        }
    }
    
    /**
     * Creates a new instance of Network with the number of neurons in each
     * layer specified in elements of numNeurons, weights specified in
     * weights[], and connections specified in connections.
     */
    public Network(
            int[] numNeurons,
            int numInputs,
            int[][][] connections,
            double[][][] weights,
            char activation) {
        if (activation == -1) activation = this.default_activation;
        int i;
        this.net[0] = new Layer(
                numNeurons[0],
                numInputs,
                weights[0],
                activation); //Make input layer
        for (i = 1; i < numNeurons.length; i++){
            // Each subsequent layers' input is the previous layers' output.
            numInputs = numNeurons[i-1];
            net[i] = new Layer(
                    numNeurons[i],
                    numInputs,
                    weights[i],
                    activation);
        } //Make middle and output layers
    }
    
    public double[] run(double[] inputs){
 
         //Send inputs to first layer, and iteratively send the outputs of each
         //Layer as inputs to the next.
        double[] values = inputs;
        for (int i = 0; i < this.net.length; i++){
            values = this.net[i].putValues(values);
        }
        return values; //return the output of the last layer
    }
}
